class Solution {
    //通过分析发现数组最右侧的点是一个特殊点，位于旋转点左侧的值均不小于它，而位于旋转点右侧的均不大于它
    //所选二分点若大于特殊点，则旋转点位于该二分点右侧，反之则位于左侧
    //二分查找:本题关键在于发现能划分并逐步缩小旋转点范围的特殊二分点
public:
    int minArray(vector<int>& numbers) {
        int numbersLength = numbers.size();  //计算数组长度
        if(0 == numbersLength)  return -1;
        if(1 == numbersLength)  return numbers[0];

        int first = 0;
        int last = numbersLength - 1;
        int temp = 0;  //二分点下标
        int lastestNumber = numbers[numbersLength - 1];
        while(first < last){
            temp = (first + last) / 2;
            if(numbers[temp] > lastestNumber){
                first = temp + 1;  //!!!注意，这种情况返回的是temp值
            }else if(numbers[temp] < lastestNumber){
                last = temp;
            }else if(numbers[temp] == lastestNumber){
                //排除特殊情况：旋转点位于数组第一位(通过顺序查找)
                //[2,1,2,2,2]原本是[1,2,2,2,2]，把1,2,2,2搬到后面
                int minOfNumbers = numbers[first];
                while(first < last){
                    if(numbers[first] > numbers[first + 1]){
                        minOfNumbers = numbers[first + 1];
                        break;
                    } 
                    ++first;
                }
                return minOfNumbers;
            }else{
                return -2;
            }
        }

        return numbers[last];
    }
};